﻿using Abp.Dependency;
using Abp.Domain.Repositories;
using Abp.Runtime.Session;
using JetBrains.Annotations;
using Mt.Site.Core.Organizations.UserCache;
using Mt.Site.Core.Organizations.UserCache.Models;
using Mt.Site.Core.WorkFlows.Design;
using Mt.Site.Core.WorkFlows.Diy.Plugin;
using Mt.Site.Core.WorkFlows.Enum;
using Mt.Site.Core.WorkFlows.Process.Entities;
using Mt.Site.Core.WorkFlows.Process.Models;
using Mt.Site.Core.WorkFlows.Process.Stores;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Mt.Site.Core.WorkFlows.Process
{
    public interface IWorkFlowManager
    {
        IIocResolver IocResolver { get; }

        IPaperContext CurrentPaper { get; }

        IAbpSession AbpSession { get; }

        IWorkFlowFactory WorkFlowFactory { get; }

        WorkFlowPluginFunctionsBase WorkFlowPluginFunction { get; }

        WorkFlowNodePluginFunctionsBase WorkFlowNodePluginFunction { get; }

        IUserAndUnitFinder UserAndUnitFinder { get; }

        IWokFlowLogStore WokFlowLogStore { get; }
        
        IWorkFlowProcessStore WorkFlowProcessStore { get; }

        IRepository<WorkFlowPaper, Guid> WorkFlowPaperRepository { get; }

        //---

        /// <summary>
        /// 被审核的数据的ID
        /// </summary>
        Guid PaperId { get; }

        Task Initialize(Guid paparId);

        /// <summary>
        /// 当前用户id
        /// </summary>
        long UserId { get; }

        /// <summary>
        /// 是否支线
        /// </summary>
        Task<bool> IsBranchLineAsync();

        /// <summary>
        /// 当前待办人在主线时 确定是否还有其他操作人员（判断是否可以提交下一步）
        /// </summary>
        Task<bool> IsMultiplePeopleAsync();

        /// <summary>
        /// 操作状态
        /// </summary>
        Task<ActionState> CheckActionStateAsync();

        /// <summary>
        /// 流程ID
        /// </summary>
        Guid WorkFlowId { get; }

        /// <summary>
        /// 过程序号
        /// </summary>
        Guid NodeId { get; }

        /// <summary>
        ///  对应的审核流程
        /// </summary>
        IWorkflowDefinition WorkFlow { get; }

        /// <summary>
        /// 对应的审核过程
        /// </summary>
        IWorkflowNodeDefinition CurrentNode { get; }

        /// <summary>
        /// 所有待办人员，追责使用，会沿责任链查找
        /// </summary>
        /// <returns></returns>
        Task<ToDoUser> GetAllOtherToDoUserIdAsync(Func<WorkFlowProcessDto, bool> exclude);

        Task<WorkFlowProcessDto> GetCurrentProcessAsync();

        /// <summary>
        /// 是否是第一步
        /// </summary>
        bool IsFirst { get; }

        /// <summary>
        /// 是否是最后一步
        /// </summary>
        Task<bool> IsLastAsync();

        /// <summary>
        /// 是否还有下一步（显示下一步按钮）
        /// </summary>
        Task<bool> CanGoNextAsync();

        /// <summary>
        /// 下一步可步入哪几个处理过程（供用户选择）
        /// </summary>
        /// <returns></returns>
        Task<IList<IWorkflowNodeDefinition>> GetNextAsync();

        /// <summary>
        /// 可退回到哪几个处理过程（供用户选择）
        /// </summary>
        /// <returns></returns>
        Task<IList<IWorkflowNodeDefinition>> GetPreAsync();

        /// <summary>
        /// 获取意见记录(只读，不要修改list里的任何model)
        /// </summary>
        Task<List<WorkFlowProcessDto>> GetAllProcessDataAsync();
        Task<List<WorkFlowProcessDto>> GetAllProcessDataWithArchiveAsync();

        /// <summary>
        /// 获取意见记录
        /// </summary>
        Task<IList<WorkFlowProcessDto>> GetRemarkDataAsync();

        /// <summary>
        /// 获取流转日志(MT_LC_JL)
        /// </summary>
        /// <returns></returns>
        Task<IList<WorkFlowLogDto>> GetLogDataAsync();


        /// <summary>
        /// 自定义操作（用于UI层遍历呈现）
        /// </summary>
        Task<List<WorkFlowActionDto>> GetActionListAsync();

        Task<StateWhenSubmit> CheckStateBeforeExecuteActionAsync(string actionName, object param);

        Task ExecuteActionAsync(string actionName, object param);

        /// <summary>
        /// 清空意见记录的缓存数据
        /// </summary>
        //void ClearRecordsCache();

        /// <summary>
        /// 是否可执行某Action
        /// </summary>
        /// <param name="key">操作名</param>
        /// <returns></returns>
        bool CanOperate(string actionName);

        /// <summary>
        /// 添加备注信息
        /// </summary>
        /// <param name="msg"></param>
        Task AddReplyAsync(string msg, string customData, bool hasRead);

        Task AddLogAsync(string message, long fromOperator, long? nextOperator, Guid? currentProcessId);
        Task AddLogAsync(string message, string fromOperator, string nextOperator, Guid? currentProcessId);

        /// <summary>
        /// 执行人任务办理完毕
        /// </summary>
        /// <param name="msg">执行人的意见</param>
        /// <param name="current">待办任务数据</param>
        /// <param name="defaultMsg">数据库中存储的意见为空，且msg参数也为空时，自动使用默认值</param>
        Task HasSolved(string replyMsg, string defaultMsg, MoveMode moveMode, Action<WorkFlowProcessDto> action = null, bool force = false);

        /// <summary>
        ///  移交下一人（等待中的人员改为todo, 不在HasSolved中直接触发，是因为HasSolved方法的调用可能只是在发起支线，当前人员并没有办完，不能移交下一个）
        /// </summary>
        /// <param name="current">当前操作人员的操作状态数据</param>
        /// <returns></returns>
        Task HandOverToNextInOrderAsync(WorkFlowProcessDto current, string replyMsg, string nextOperator = null);

        /// <summary>
        /// 在主线上增加新的待办任务
        /// </summary>
        /// <param name="current">当前操作人员的操作状态数据</param>
        /// <param name="userIds">接手人的id序列</param>
        /// <param name="turnRoundUserList">接手人的id序列(传阅)</param>
        /// <param name="nodeId">步骤的ID</param>
        /// <param name="isNewStep">是否是进入下一步</param>
        /// <param name="actionScheme">执行模式：actionScheme</param>
        /// <param name="actionScheme">催办，追责时的责任人(null:自行负责，id: 责任人的任务id)</param>
        Task AddNewTaskInTrunkAsync(
             WorkFlowProcessDto current, 
             List<long> userIds, List<long> turnRoundUserList, 
             Guid nodeId, bool isNewStep, ActionScheme actionScheme, Guid? responsibilityId);

        /// <summary>
        /// 增加支线待办任务 (支线上不能添加传阅任务，为避免错误调用及简化参数，所以做了拆分)
        /// </summary>
        /// <param name="current">当前操作人员的操作状态数据</param>
        /// <param name="userIds">接手人的id序列</param>
        /// <param name="actionScheme">执行模式：actionScheme</param>
        /// <param name="actionScheme">催办，追责时的责任人(null:自行负责，id: 责任人的任务id)</param>
        Task AddNewTaskInBranchAsync(
            [NotNull]WorkFlowProcessDto current, [NotNull] List<long> userIds, ActionScheme actionScheme, Guid? responsibilityId);

        Task AddNewTaskInTrunkAsync(
            WorkFlowProcessDto current,
            [NotNull] List<WfUserQueueItem> users, List<WfUserQueueItem> turnRoundUser,
            Guid nodeId, bool isNewStep, ActionScheme actionScheme);

        Task<List<WorkFlowProcessDto>> AddNewTaskAsync(WorkFlowProcessDto current, [NotNull] Queue<List<WfUserQueueItem>> userQueue, Guid nodeId,
             string parentCode, int lastUnitCode, ActionScheme actionScheme, Guid? trunkId, int stepCode);

        /// <summary>
        /// 下一步操作（主线流程前往下一步）
        /// </summary>
        /// <param name="nodeId"></param>
        /// <param name="userids_next">支线时无需传入</param>
        /// <param name="actionScheme_next">支线时无需传入</param>
        Task GoNextAsync(Guid nodeId, List<long> userids_next, List<long> turnRoundUserList, ActionScheme actionScheme_next, string replyMsg);

        /// <summary>
        /// 下一步操作（支线流程前往下一步）
        /// </summary>
        /// <returns>true表示符合本方法的调用条件</returns>
        Task<bool> GoNextAsync(string replyMsg);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="current"></param>
        /// <param name="userids_next"></param>
        /// <param name="turnRoundUserList"></param>
        /// <param name="nodeId"></param>
        /// <param name="actionScheme_next"></param>
        /// <param name="replyMsg"></param>
        /// <returns></returns>
        Task GoNext(
            WorkFlowProcessDto current, List<long> userids_next, List<long> turnRoundUserList, Guid nodeId,
            ActionScheme actionScheme_next, string replyMsg, Action<WorkFlowProcessDto> action = null);

        Task GoNext(
            WorkFlowProcessDto current, List<WfUserQueueItem> users_next, List<WfUserQueueItem> turnRoundUserList, Guid nodeId,
            ActionScheme actionScheme_next, string replyMsg,
            Action<WorkFlowProcessDto> action = null);

        /// <summary>
        /// 添加新稿件（主线流程的入口）
        /// </summary>
        Task AddManuscriptAsync(IWorkflowDefinition workflow, string title);


        /// <summary>
        /// 是否可以退回（显示退回按钮）
        /// </summary>
        Task<bool> CanGoback();

        /// <summary>
        /// 退回（仅主线可以退回）
        /// </summary>
        /// <param name="nodeId"></param>
        /// <returns></returns>
        Task GoBackAsync(Guid nodeId,string replyMsg);

        Task<bool> IsHasOtherOperatorAsync(WorkFlowProcessDto current);

        /// <summary>
        /// 避免用户有两个待办任务
        /// </summary>
        /// <param name="userList"></param>
        /// <returns></returns>
        Task<List<long>> RemoveToDoStateUserBeforeAddTaskAsync(List<long> userList);
        
        /// <summary>
        /// 查找所有处理待办或等待状态的待处理任务（不包含待阅），用于添加新任务时，避免重复
        /// </summary>
        /// <returns></returns>
        Task<List<long>> GetToDoUserListAsync();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="nodeId"></param>
        /// <param name="unitIdList">用户搜索的范围</param>
        /// <param name="userFilter"></param>
        /// <returns></returns>
        Task<GetUserSelectionDataOutput> GetUserListAsync(Guid? nodeId, List<long> unitId, UserFilter userFilter, string signal = null);

        Task<GetUserSelectionDataOutput> GetUserListForActionAsync(Guid? nodeId, List<long> unitIdList, [NotNull]string actionName);

        Task TryAddAdditionalMsg(string msg);
        Task<List<WorkFlowProcessMsgDto>> GetAllAdditionalMsg();

        Task<List<WorkFlowRelationshipDto>> GetWorkFlowRelationshipsAsync();

        Task<List<WorkFlowRelationshipDto>> GetWorkFlowRelationshipsWithCanceledAsync();

        void ChangeProcessDataToArchive(WorkFlowProcessDto current, WorkFlowProcessDto item);

        /// <summary>
        /// 对旧状态数据修改后（清空备注，状态位恢复等）重新写入(插入新的待办任务) ,与原数据拥有相同的trunkId, Code
        /// </summary>
        /// <param name="oldData">接手人的操作状态数据</param>
        /// <param name="current">当前操作人员的操作状态数据</param>
        /// <param name="stepCode">当前操作人员的操作状态数据</param>
        /// <returns></returns>
        void AddNewTaskByAlterOldTask(WorkFlowProcessDto oldData, WorkFlowProcessDto current, int stepCode);

        Task ResetRuntimeDataAsync();

        /**
         * 审核状态
         */
        void AdjustAprovealResultStatus();
    }
}
